#require 'memcache-client'

# in config.rb
#CACHE = MemCache.new 'localhost:11211', :multithread => true, :namespace => 'reality_spec'

module Sequel
  class Dataset
    def cache_proxy
      @opts[:cache_proxy]
    end
    
    def cache_by(*keys)
      @opts[:cache_proxy] = CacheProxy.new(@opts[:from])
      @opts[:cache_keys] = keys
    end
    
    alias_method :orig_brackets, :[]
    
    def [](*args)
      if @opts[:cache_proxy] && (args.size == @opts[:cache_keys].size) && \
        !args.first.is_a?(Hash)
        cached = @opts[:cache_proxy].get(args)
        return cached if cached
      end
      orig_brackets(args)
    end
  end
  
  class CacheProxy
    attr_reader :prefix
    attr_accessor :ttl
    
    def initialize(prefix, ttl = 900)
      @prefix = "#{prefix}#{__id___}"
      @ttl = ttl
    end
    
    def format_key(key)
      "#{@prefix}#{key.inspect}"
    end
    
    def get(key)
      CACHE.get(format_key(key))
    end
    
    def set(key, value)
      CACHE.set(format_key(key), value, @ttl)
    end
    
    def delete(key)
      CACHE.delete(format_key(key))
    end
  end
end

items = DB[:items].cache_by(:name)

i1 = items['joojoo'] # DB hit
i2 = items['joojoo'] # cache hit

items.filter(:name => 'joojoo').update(:name => '10') # cache invalidated

# composite cache keys

attributes = DB[:items].cache_by(:node_id, :kind)

i1 = attributes[@n_id, Attributes::SampleRate] # DB hit
i2 = attributes[@n_id, Attributes::SampleRate] # cache hit

attributes[@n_id, Attributes::SampleRate] = {:value => 10} # hit
